import os
import uuid
import json
import requests
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
from pathlib import Path
from datetime import datetime
from config import Config
from layered_image_processor import LayeredImageProcessor
from photoshop_compatible_processor import PhotoshopCompatibleProcessor
from photoshop_tiff_processor import PhotoshopTiffProcessor
from practical_solution import PracticalTiffProcessor
from psd_processor import PSDProcessor
from hybrid_solution import HybridSolution
from advanced_photoshop_solution import AdvancedPhotoshopSolution

class ImageProcessor:
    def __init__(self):
        self.export_folder = Config.EXPORT_FOLDER
        self.upload_folder = Config.UPLOAD_FOLDER
        # 初始化图层处理器
        self.layered_processor = LayeredImageProcessor()
        # 初始化PS兼容处理器
        self.ps_processor = PhotoshopCompatibleProcessor()
        # 初始化Photoshop TIFF处理器
        self.ps_tiff_processor = PhotoshopTiffProcessor()
        # 初始化实用TIFF处理器
        self.practical_processor = PracticalTiffProcessor()
        # 初始化PSD处理器
        self.psd_processor = PSDProcessor()
        # 初始化混合解决方案
        self.hybrid_solution = HybridSolution()
        # 初始化高级Photoshop解决方案
        self.advanced_ps_solution = AdvancedPhotoshopSolution()
        
    def download_image_from_url(self, url):
        """从URL下载图片"""
        try:
            response = requests.get(url, timeout=30)
            response.raise_for_status()
            return Image.open(BytesIO(response.content))
        except Exception as e:
            print(f"下载图片失败 {url}: {e}")
            # 返回一个占位符图片
            return self.create_placeholder_image(300, 300, f"图片加载失败\\n{url}")
    
    def create_placeholder_image(self, width, height, text="占位符"):
        """创建占位符图片"""
        img = Image.new('RGB', (width, height), color='#f0f0f0')
        draw = ImageDraw.Draw(img)
        
        # 尝试使用系统字体，如果失败则使用默认字体
        try:
            font = ImageFont.truetype("arial.ttf", 16)
        except:
            try:
                font = ImageFont.truetype("simhei.ttf", 16)  # 中文字体
            except:
                font = ImageFont.load_default()
        
        # 计算文本位置（居中）
        bbox = draw.textbbox((0, 0), text, font=font)
        text_width = bbox[2] - bbox[0]
        text_height = bbox[3] - bbox[1]
        x = (width - text_width) // 2
        y = (height - text_height) // 2
        
        draw.text((x, y), text, fill='#666666', font=font)
        return img
    
    def resize_image_to_fit(self, image, target_width, target_height, maintain_aspect=True):
        """调整图片大小以适应目标区域"""
        if maintain_aspect:
            # 保持宽高比，适应区域
            image.thumbnail((target_width, target_height), Image.Resampling.LANCZOS)
            return image
        else:
            # 拉伸填满区域
            return image.resize((target_width, target_height), Image.Resampling.LANCZOS)
    
    def apply_transformations(self, image, user_placement_data):
        """应用用户的变换操作（缩放、旋转等）"""
        # 获取用户设置的缩放比例
        scale_data = user_placement_data.get('scale', {})
        scale_x = scale_data.get('scale_x', 1.0)
        scale_y = scale_data.get('scale_y', 1.0)
        
        # 应用缩放
        if scale_x != 1.0 or scale_y != 1.0:
            new_width = int(image.width * scale_x)
            new_height = int(image.height * scale_y)
            image = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
        
        # 获取旋转角度
        angle = user_placement_data.get('angle_of_rotation', 0)
        if angle != 0:
            image = image.rotate(angle, expand=True, fillcolor=(255, 255, 255, 0))
        
        return image
    
    def create_customized_image(self, template, regions, customization_data, export_format='png', preserve_layers=False, custom_filename='', layer_adjustments=None):
        """创建定制后的图片
        
        Args:
            template: 底板模板信息
            regions: 区域信息  
            customization_data: 定制数据
            export_format: 导出格式
            preserve_layers: 是否保留图层信息（仅对TIFF格式有效）
            custom_filename: 自定义文件名（不包含扩展名）
        """
        # 如果需要保留图层，根据格式和文件类型选择处理器
        if preserve_layers and export_format.lower() in ['tif', 'tiff', 'psd']:
            # 检查是否为PSD文件
            from pathlib import Path
            image_path = template.get('image_path', '')
            if image_path and Path(image_path).suffix.lower() == '.psd':
                print("使用高级Photoshop解决方案...")
                return self.advanced_ps_solution.create_advanced_export(
                    template, regions, customization_data, export_format, custom_filename
                )
            else:
                print("使用实用TIFF模式处理图片...")
                return self.practical_processor.create_enhanced_tiff(
                    template, regions, customization_data, custom_filename
                )
        
        # 否则使用原有的合并模式
        # 创建底板画布
        canvas_width = template['width']
        canvas_height = template['height']
        
        # 创建白色背景的画布
        canvas = Image.new('RGBA', (canvas_width, canvas_height), (255, 255, 255, 255))
        
        # 如果底板有图片文件，加载它
        if template.get('image_path'):
            try:
                from pathlib import Path
                image_path = template['image_path']
                
                # 判断是绝对路径还是相对路径
                if Path(image_path).is_absolute():
                    # 绝对路径 - 直接使用本地文件
                    template_image_path = Path(image_path)
                else:
                    # 相对路径 - 在uploads目录中
                    template_image_path = self.upload_folder / image_path
                
                if template_image_path.exists():
                    # 如果有图层颜色调整，先应用调整
                    if layer_adjustments and len(layer_adjustments) > 0:
                        print("应用图层颜色调整到底板...")
                        adjusted_path = self.apply_template_layer_adjustments(template, layer_adjustments)
                        if adjusted_path and adjusted_path.exists():
                            base_image = Image.open(adjusted_path)
                            print("✅ 使用颜色调整后的底板")
                        else:
                            base_image = Image.open(template_image_path)
                            print("⚠️ 图层调整失败，使用原始底板")
                    else:
                        base_image = Image.open(template_image_path)
                    
                    # 保持原始尺寸比例，不强制拉伸
                    if base_image.size != (canvas_width, canvas_height):
                        # 如果尺寸不匹配，使用contain模式保持比例
                        base_image.thumbnail((canvas_width, canvas_height), Image.Resampling.LANCZOS)
                        
                        # 创建居中的图片
                        centered_image = Image.new('RGBA', (canvas_width, canvas_height), (255, 255, 255, 0))
                        x_offset = (canvas_width - base_image.width) // 2
                        y_offset = (canvas_height - base_image.height) // 2
                        centered_image.paste(base_image, (x_offset, y_offset))
                        base_image = centered_image
                    
                    if base_image.mode != 'RGBA':
                        base_image = base_image.convert('RGBA')
                    canvas = Image.alpha_composite(canvas, base_image)
                    print(f"已加载底板图片: {image_path}")
                    print(f"底板图片尺寸: {base_image.size}")
                else:
                    print(f"底板图片文件不存在: {template_image_path}")
            except Exception as e:
                print(f"加载底板图片失败: {e}")
        
        # 如果有底板图片URL，先加载底板图片
        base_image_url = customization_data.get('base_image_url')
        if base_image_url:
            try:
                base_image = self.download_image_from_url(base_image_url)
                base_image = base_image.resize((canvas_width, canvas_height), Image.Resampling.LANCZOS)
                if base_image.mode != 'RGBA':
                    base_image = base_image.convert('RGBA')
                canvas = Image.alpha_composite(canvas, base_image)
                print(f"已加载底板URL图片: {base_image_url}")
            except Exception as e:
                print(f"加载底板URL图片失败: {e}")
        
        # 处理每个定制区域
        processed_count = 0
        
        print("开始处理定制数据...")
        print("regions数据:", customization_data.get('regions', {}))
        print("数据库regions数量:", len(regions))
        
        # 直接处理customization_data中的regions
        for region_index, region_data in customization_data.get('regions', {}).items():
            print(f"处理区域索引 {region_index}:")
            
            # 获取该区域的图片数据
            elements = region_data.get('elements', [])
            print(f"区域索引 {region_index} 有 {len(elements)} 个元素")
            
            for element in elements:
                try:
                    # 使用虚拟区域对象（因为我们主要需要的是元素数据）
                    virtual_region = {
                        'id': region_index,
                        'name': f'区域_{region_index}',
                        'x': 0,
                        'y': 0,
                        'width': canvas_width,
                        'height': canvas_height
                    }
                    
                    if self._process_region_element(canvas, virtual_region, element):
                        processed_count += 1
                        print(f"成功处理元素: {element.get('image_url', 'Unknown')}")
                except Exception as e:
                    print(f"处理区域元素失败: {e}")
                    continue
        
        print(f"总共处理了 {processed_count} 个图片元素")
        
        # 生成文件名
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        unique_id = str(uuid.uuid4())[:8]
        
        # 使用自定义文件名或默认文件名
        if custom_filename:
            # 清理文件名，移除不安全字符
            import re
            safe_filename = re.sub(r'[<>:"/\\|?*]', '_', custom_filename)
            base_filename = safe_filename[:50]  # 限制长度
        else:
            base_filename = f"customized_{timestamp}_{unique_id}"
        
        # 根据格式设置文件扩展名和保存参数
        if export_format in ['jpg', 'jpeg']:
            if custom_filename:
                filename = f"{base_filename}.jpg"
            else:
                filename = f"customized_{timestamp}_{unique_id}.jpg"
            save_format = 'JPEG'
            save_kwargs = {'quality': 95}
            # JPEG不支持透明度，需要白色背景
            if canvas.mode == 'RGBA':
                rgb_canvas = Image.new('RGB', canvas.size, (255, 255, 255))
                rgb_canvas.paste(canvas, mask=canvas.split()[-1])
                canvas = rgb_canvas
        elif export_format in ['tif', 'tiff']:
            if custom_filename:
                filename = f"{base_filename}.tif"
            else:
                filename = f"merged_{timestamp}_{unique_id}.tif"
            save_format = 'TIFF'
            save_kwargs = {'compression': 'lzw'}
            # TIF支持RGBA，保持原始模式
            print("注意：使用合并模式保存TIFF，图层信息将丢失。如需保留图层，请在导出时选择'保留图层'选项。")
        else:  # png
            if custom_filename:
                filename = f"{base_filename}.png"
            else:
                filename = f"customized_{timestamp}_{unique_id}.png"
            save_format = 'PNG'
            save_kwargs = {'optimize': True}
            # PNG支持RGBA，保持原始模式
        
        export_path = self.export_folder / filename
        
        # 保存图片
        canvas.save(export_path, save_format, **save_kwargs)
        print(f"图片已保存到: {export_path} (格式: {save_format})")
        return export_path
    
    def _process_region_element(self, canvas, region, element):
        """处理单个区域元素"""
        image_url = element.get('image_url')
        if not image_url:
            print("元素没有image_url")
            return False
        
        print(f"正在处理图片: {image_url}")
        
        # 下载图片
        element_image = self.download_image_from_url(image_url)
        if not element_image:
            print(f"下载图片失败: {image_url}")
            return False
        
        print(f"图片下载成功，尺寸: {element_image.size}")
        
        # 转换为RGBA模式
        if element_image.mode != 'RGBA':
            element_image = element_image.convert('RGBA')
        
        # 获取用户放置数据
        user_placement_data = element.get('user_placement_data', {})
        
        # 获取放置位置
        position = user_placement_data.get('position', {})
        x = int(position.get('x', region['x']))
        y = int(position.get('y', region['y']))
        
        print(f"放置位置: ({x}, {y})")
        
        # 获取缩放信息
        scale = user_placement_data.get('scale', {})
        scale_x = scale.get('scale_x', 1.0)
        scale_y = scale.get('scale_y', 1.0)
        
        # 获取实际显示尺寸（从dimension字段）
        dimension = user_placement_data.get('dimension', {})
        target_width = dimension.get('width')
        target_height = dimension.get('height')
        
        # 如果有dimension数据，直接使用；否则使用scale计算
        if target_width and target_height:
            new_width = int(target_width)
            new_height = int(target_height)
            element_image = element_image.resize((new_width, new_height), Image.Resampling.LANCZOS)
            print(f"图片调整为目标尺寸: {element_image.size}")
        elif scale_x != 1.0 or scale_y != 1.0:
            new_width = int(element_image.width * scale_x)
            new_height = int(element_image.height * scale_y)
            element_image = element_image.resize((new_width, new_height), Image.Resampling.LANCZOS)
            print(f"图片按比例缩放: {element_image.size}")
        
        # 获取旋转角度
        angle = user_placement_data.get('angle_of_rotation', 0)
        if angle != 0:
            element_image = element_image.rotate(angle, expand=True, fillcolor=(255, 255, 255, 0))
            print(f"图片旋转角度: {angle}")
        
        # 确保图片不超出画布边界
        x = max(0, min(x, canvas.width - element_image.width))
        y = max(0, min(y, canvas.height - element_image.height))
        
        print(f"最终放置位置: ({x}, {y}), 图片尺寸: {element_image.size}")
        
        # 粘贴图片到画布
        try:
            canvas.paste(element_image, (x, y), element_image)
            print("图片粘贴成功")
            return True
        except Exception as e:
            print(f"粘贴图片失败: {e}")
            return False
    
    def create_preview_image(self, template, regions, customization_data, max_size=800):
        """创建预览图片（较小尺寸）"""
        # 先创建完整图片
        full_image_path = self.create_customized_image(template, regions, customization_data)
        
        # 加载并缩放为预览尺寸
        with Image.open(full_image_path) as img:
            img.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)
            
            # 生成预览文件名
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            unique_id = str(uuid.uuid4())[:8]
            preview_filename = f"preview_{timestamp}_{unique_id}.png"
            preview_path = self.export_folder / preview_filename
            
            img.save(preview_path, 'PNG')
            return preview_path
    
    def apply_template_layer_adjustments(self, template, layer_adjustments):
        """
        应用图层颜色调整，生成调整后的底板
        
        Args:
            template: 底板模板信息
            layer_adjustments: 图层颜色调整参数
            
        Returns:
            Path: 调整后的底板文件路径
        """
        print("=== 应用图层颜色调整 ===")
        
        if not layer_adjustments:
            print("没有颜色调整信息")
            return None
        
        try:
            from pathlib import Path
            from PIL import ImageEnhance, ImageOps
            import colorsys
            
            image_path = template.get('image_path', '')
            if not image_path:
                print("底板没有图片文件")
                return None
            
            # 确定文件路径
            if Path(image_path).is_absolute():
                template_path = Path(image_path)
            else:
                template_path = self.upload_folder / image_path
            
            if not template_path.exists():
                print(f"底板文件不存在: {template_path}")
                return None
            
            # 根据文件类型处理
            if template_path.suffix.lower() == '.psd':
                return self._apply_psd_layer_adjustments(template_path, layer_adjustments)
            else:
                return self._apply_image_color_adjustments(template_path, layer_adjustments)
                
        except Exception as e:
            print(f"应用图层调整失败: {e}")
            return None
    
    def _apply_psd_layer_adjustments(self, psd_path, layer_adjustments):
        """应用PSD图层颜色调整"""
        try:
            from psd_tools import PSDImage
            from PIL import ImageEnhance, ImageOps, ImageChops
            
            # 打开PSD文件
            psd = PSDImage.open(psd_path)
            
            # 创建调整后的PSD画布
            canvas = Image.new('RGBA', (psd.width, psd.height), (255, 255, 255, 0))
            
            # 逐层处理并合成
            for layer_index, layer in enumerate(psd):
                try:
                    layer_img = layer.composite()
                    if not layer_img:
                        continue
                    
                    # 检查是否有颜色调整
                    if str(layer_index) in layer_adjustments:
                        adjustments = layer_adjustments[str(layer_index)]
                        color = adjustments.get('color', '#ffffff')
                        
                        if color != '#ffffff':
                            # 应用颜色叠加到这个图层
                            layer_img = self._apply_color_overlay_to_layer(layer_img, color)
                            print(f"✅ 应用图层 {layer_index} ({layer.name}) 的颜色调整: {color}")
                    
                    # 合成到画布
                    if layer_img.size == canvas.size:
                        canvas = Image.alpha_composite(canvas, layer_img.convert('RGBA'))
                    
                except Exception as layer_error:
                    print(f"处理图层 {layer_index} 失败: {layer_error}")
                    continue
            
            # 保存调整后的文件
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            adjusted_filename = f"adjusted_template_{timestamp}.png"
            adjusted_path = self.export_folder / adjusted_filename
            
            # 转换为RGB并保存
            if canvas.mode == 'RGBA':
                rgb_canvas = Image.new('RGB', canvas.size, (255, 255, 255))
                rgb_canvas.paste(canvas, mask=canvas.split()[-1])
                canvas = rgb_canvas
            
            canvas.save(adjusted_path, 'PNG', optimize=True)
            print(f"保存调整后的PSD底板: {adjusted_path}")
            
            return adjusted_path
            
        except Exception as e:
            print(f"PSD图层调整失败: {e}")
            return None
    
    def _apply_color_overlay_to_layer(self, layer_img, color):
        """对单个图层应用颜色叠加"""
        try:
            from PIL import ImageChops
            
            # 确保是RGBA模式
            if layer_img.mode != 'RGBA':
                layer_img = layer_img.convert('RGBA')
            
            # 创建颜色叠加层
            color_rgb = self._hex_to_rgba(color, 128)  # 50%透明度
            overlay = Image.new('RGBA', layer_img.size, color_rgb)
            
            # 使用overlay混合模式
            result = ImageChops.overlay(layer_img, overlay)
            
            return result
            
        except Exception as e:
            print(f"图层颜色叠加失败: {e}")
            return layer_img
    
    def _apply_image_color_adjustments(self, image_path, layer_adjustments):
        """应用普通图片的颜色调整"""
        try:
            from PIL import ImageEnhance
            
            # 打开图片
            with Image.open(image_path) as img:
                # 转换为RGBA模式
                if img.mode != 'RGBA':
                    img = img.convert('RGBA')
                
                # 应用第一个图层的调整（对于非PSD文件）
                if '0' in layer_adjustments:
                    adjustments = layer_adjustments['0']
                    img = self._apply_color_adjustments_to_image(img, adjustments)
                
                # 保存调整后的文件
                timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
                adjusted_filename = f"adjusted_template_{timestamp}.png"
                adjusted_path = self.export_folder / adjusted_filename
                
                # 转换为RGB并保存
                if img.mode == 'RGBA':
                    rgb_img = Image.new('RGB', img.size, (255, 255, 255))
                    rgb_img.paste(img, mask=img.split()[-1])
                    img = rgb_img
                
                img.save(adjusted_path, 'PNG', optimize=True)
                print(f"保存调整后的图片底板: {adjusted_path}")
                
                return adjusted_path
                
        except Exception as e:
            print(f"图片颜色调整失败: {e}")
            return None
    
    def _apply_color_adjustments_to_image(self, image, adjustments):
        """对单张图片应用颜色调整"""
        try:
            from PIL import ImageEnhance, ImageOps, ImageChops
            
            # 确保是RGBA模式
            if image.mode != 'RGBA':
                image = image.convert('RGBA')
            
            result_img = image.copy()
            
            # 新的颜色叠加方式
            color = adjustments.get('color', '#ffffff')
            intensity = adjustments.get('intensity', 20) / 100.0
            
            if color != '#ffffff' and intensity > 0:
                # 创建颜色叠加层
                overlay = Image.new('RGBA', image.size, self._hex_to_rgba(color, int(255 * intensity)))
                
                # 使用multiply混合模式进行颜色叠加
                result_img = ImageChops.multiply(result_img, overlay)
                
                print(f"应用颜色叠加: {color}, 强度: {intensity * 100}%")
            
            return result_img
            
        except Exception as e:
            print(f"颜色调整处理失败: {e}")
            return image
    
    def _hex_to_rgba(self, hex_color, alpha=255):
        """将十六进制颜色转换为RGBA元组"""
        hex_color = hex_color.lstrip('#')
        return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4)) + (alpha,)
    
    def _adjust_hue(self, image, hue_shift):
        """调整图片色调"""
        try:
            import colorsys
            pixels = image.load()
            width, height = image.size
            
            for x in range(width):
                for y in range(height):
                    r, g, b, a = pixels[x, y]
                    
                    # 转换到HSV
                    h, s, v = colorsys.rgb_to_hsv(r/255.0, g/255.0, b/255.0)
                    
                    # 调整色调
                    h = (h + hue_shift/360.0) % 1.0
                    
                    # 转换回RGB
                    r, g, b = colorsys.hsv_to_rgb(h, s, v)
                    pixels[x, y] = (int(r*255), int(g*255), int(b*255), a)
            
            return image
            
        except Exception as e:
            print(f"色调调整失败: {e}")
            return image
    
    def _replace_color(self, image, source_color, target_color):
        """替换图片中的颜色"""
        try:
            # 将颜色字符串转换为RGB
            source_rgb = tuple(int(source_color[i:i+2], 16) for i in (1, 3, 5))
            target_rgb = tuple(int(target_color[i:i+2], 16) for i in (1, 3, 5))
            
            pixels = image.load()
            width, height = image.size
            
            # 颜色容差
            tolerance = 30
            
            for x in range(width):
                for y in range(height):
                    r, g, b, a = pixels[x, y]
                    
                    # 检查是否接近源颜色
                    color_distance = ((r - source_rgb[0])**2 + 
                                    (g - source_rgb[1])**2 + 
                                    (b - source_rgb[2])**2) ** 0.5
                    
                    if color_distance <= tolerance:
                        # 替换为目标颜色
                        pixels[x, y] = (target_rgb[0], target_rgb[1], target_rgb[2], a)
            
            return image
            
        except Exception as e:
            print(f"颜色替换失败: {e}")
            return image